library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity xmt_Control is
port (
		busIn      : in std_logic_vector(7 downto 0);   --from RCV mux
		correctPort     : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
		port_Ready        : IN STD_LOGIC;
		spaceAvail0     : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
		spaceAvail1     : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
		spaceAvail2     : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
		spaceAvail3     : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
		size       : in std_logic_vector(11 downto 0);   --frame length
		spaceValid : out std_logic;
		sizeOut    : out std_logic_vector(11 downto 0);
		busOut     : out std_logic_vector(7 downto 0)   --to demux for transmission
     );
end xmt_Control;

architecture control_arch of xmt_Control is
	COMPONENT CLA12 is 
		PORT( a,b				:IN 	STD_LOGIC_VECTOR(11 DOWNTO 0);
			  output			:OUT	STD_LOGIC_VECTOR(11 DOWNTO 0)
		);
	END COMPONENT;
	
	component mux2
		PORT
		(
			data0x		: IN STD_LOGIC_VECTOR (11 DOWNTO 0);
			data1x		: IN STD_LOGIC_VECTOR (11 DOWNTO 0);
			sel		: IN STD_LOGIC ;
			result		: OUT STD_LOGIC_VECTOR (11 DOWNTO 0)
		);
	end component;
	
	component mux3
		PORT
		(
		data0		: IN STD_LOGIC ;
		data1		: IN STD_LOGIC ;
		sel		: IN STD_LOGIC ;
		result		: OUT STD_LOGIC 
		);
	end component;

	
	component not_gate
	PORT
		(
		data		: IN STD_LOGIC_VECTOR (11 DOWNTO 0);
		result		: OUT STD_LOGIC_VECTOR (11 DOWNTO 0)
		);
	end component;
	
signal compareOut0,compareOut1,compareOut2,compareOut3: STD_LOGIC_VECTOR(11 DOWNTO 0);
signal not_Size0, not_Size1,not_Size2,not_Size3, spaceAvail: STD_LOGIC_VECTOR(11 DOWNTO 0);
signal sizeOut0, sizeOut1, sizeOut2,sizeOut3 : STD_LOGIC_VECTOR(11 DOWNTO 0);
signal ACK_out0,ACK_out1,ACK_out2,ACK_out3,ACK_out4 : STD_LOGIC;

begin	 
compareSize0: CLA12 PORT MAP(not_Size0, spaceAvail0, compareOut0);
notSizeGate0: not_gate PORT MAP(size, not_Size0);
compareMux0 : mux2 PORT MAP(size, "000000000000", compareOut0(11),sizeOut0);
ackMux0     : mux3 PORT MAP('1', '0',compareOut0(11),ACK_out0);

compareSize1: CLA12 PORT MAP(not_Size1, spaceAvail1, compareOut1);
notSizeGate1: not_gate PORT MAP(size, not_Size1);
compareMux1 : mux2 PORT MAP(size, "000000000000", compareOut1(11),sizeOut1);
ackMux1     : mux3 PORT MAP('1', '0',compareOut1(11),ACK_out1);

compareSize2: CLA12 PORT MAP(not_Size2, spaceAvail2, compareOut2);
notSizeGate2: not_gate PORT MAP(size, not_Size2);
compareMux2 : mux2 PORT MAP(size, "000000000000", compareOut2(11),sizeOut2);
ackMux2     : mux3 PORT MAP('1', '0',compareOut2(11),ACK_out2);

compareSize3: CLA12 PORT MAP(not_Size3, spaceAvail3, compareOut3);
notSizeGate3: not_gate PORT MAP(size, not_Size3);
compareMux3 : mux2 PORT MAP(size, "000000000000", compareOut3(11),sizeOut3);
ackMux3     : mux3 PORT MAP('1', '0',compareOut3(11),ACK_out3);

Process (busIn, correctPort, port_Ready, ACK_out0, ACK_out1, ACK_out2, ACK_out3,
		sizeOut0, sizeOut1, sizeOut2, sizeOut3)
	Begin
	IF(port_Ready<='1'AND correctPort(2)='0') THEN
		busOut<= busIn;
		case correctPort is
		  when "000" => spaceValid<=ACK_out0; sizeOut<=sizeOut0;
		  when "001" => spaceValid<=ACK_out1; sizeOut<=sizeOut1;
		  when "010" => spaceValid<=ACK_out2; sizeOut<=sizeOut2;
		  when "011" => spaceValid<=ACK_out3; sizeOut<=sizeOut3;
		  when "100" => spaceValid<=ACK_out3; sizeOut<=sizeOut3;
		  when "101" => spaceValid<=ACK_out3; sizeOut<=sizeOut3;
		  when "110" => spaceValid<=ACK_out3; sizeOut<=sizeOut3;
		  when "111" => spaceValid<=ACK_out3; sizeOut<=sizeOut3;
		end case;
	
	ELSIF(port_Ready<='1' AND correctPort(2)='1') THEN
		IF(ACK_out0 ='1'AND ACK_out1 ='1' AND ACK_out2 ='1' AND ACK_out3 ='1') THEN
			spaceValid<='1';
			sizeOut<=sizeOut0;
		ELSE
			spaceValid<='0';
		END IF;
	END IF;
END PROCESS;
end control_arch;